-
Notifications
You must be signed in to change notification settings - Fork 3.1k
lib/libc: fix bug in parsing in getopt #1918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Thank you for taking the time to contribute to FreeBSD! |
|
This probably needs to be backported, but as this is my first contribution I am not sure about the proper workflow on this._ |
jlduran
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should manually pass the following three tests (at least):
$ ./getoptest -l -w -d14 -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is 14
ch is s optarg is /usr/local/admin/tftproot
ch is u optarg is admin
ch is U optarg is 0
$ ./getoptest -l -w -d 14 -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is 14 # XXX <- (Or is it NULL? I'll have to test on Linux)
ch is s optarg is /usr/local/admin/tftproot
ch is u optarg is admin
ch is U optarg is 0
and
$ ./getoptest -l -w -d -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is NULL
ch is s optarg is /usr/local/admin/tftproot
ch is u optarg is admin
ch is U optarg is 0
lib/libc/stdlib/getopt.c
Outdated
| if (*place) | ||
| optarg = place; | ||
| else if (oli[2] == ':') | ||
| else if (oli[2] == ':') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The style(9) fixes I was referring to in the bug report should be addressed, maybe using NetBSD style guide (https://cvsweb.netbsd.org/bsdweb.cgi/src/share/misc/style?rev=HEAD&content-type=text/x-cvsweb-markup).
Basically, use tabs, not spaces for indentation, and braces around single-line bodies are optional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review. I fixed the tabs. Not sure on the braces. It is a "single instruction" but it is another nested if/else. Not contesting any of it, just unsure which one would be preferred.
As for the tests:
rootnode@x220 ~/c/c/291374> ./getopttest -l -w -d14 -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is 14
ch is s optarg is /usr/local/admin/tftproot
ch is u optarg is admin
ch is U optarg is 0
rootnode@x220 ~/c/c/291374> ./getopttest -l -w -d 14 -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is 14
ch is s optarg is /usr/local/admin/tftproot
ch is u optarg is admin
ch is U optarg is 0
rootnode@x220 ~/c/c/291374> ./getopttest -l -w -d -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is NULL
ch is s optarg is /usr/local/admin/tftproot
ch is u optarg is admin
ch is U optarg is 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm missing something, this patch does not match the one from the bug report, nor it passes the tests above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm missing something, this patch does not match the one from the bug report, nor it passes the tests above.
I mixed up the two branches between my 2 machines. One wasn't up to date. You refer to the missing && nargv[optind + 1][0] != '-'?
After some testing it turned out that this would for example segfault on ./getopttest -d -14
At that point it comes down to interpretation I guess. Is the - in the value argument allowed or should it be quoted to be allowed.
The version in this PR is not segfaulting and allows for - values.
$ ./getoptest -l -w -d -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is -s
Should the value 14 be missing as in the example above, then it would stop parsing at that point and return an error.
As I understand it, the man page description allows for the whitespace followed by any value.
But you are correct, the 3rd case would be broken.
I'll see if I can mitigate the segfault and get the 3rd case working. Values starting with a - might have to be quoted then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, so let's add that 4th test:
./getoptest -l -w -d -14 -s /usr/local/admin/tftproot -u admin -U 0
ch is l optarg is NULL
ch is w optarg is NULL
ch is d optarg is NULL
./getoptest: illegal option -- 1
ch is ? optarg is NULL
./getoptest: illegal option -- 4
ch is ? optarg is NULL
ch is s optarg is /usr/local/admin/tftproot
ch is u optarg is admin
ch is U optarg is 0
EDIT: Match the expected FreeBSD output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean as the expected behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean as the expected behavior?
Yes, unless you have a different suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion makes sense. I will make the appropriate changes. Will take bit due to timezones.
|
So, I have the following patch you submitted in the Buzgilla Problem Report 291374 (adjusted to match style(9)): --- a/lib/libc/stdlib/getopt.c
+++ b/lib/libc/stdlib/getopt.c
@@ -107,13 +107,16 @@ getopt(int nargc, char * const nargv[], const char *ostr)
entire next argument. */
if (*place)
optarg = place;
- else if (oli[2] == ':')
+ else if (oli[2] == ':') {
/*
* GNU Extension, for optional arguments if the rest of
* the argument is empty, we return NULL
*/
- optarg = NULL;
- else if (nargc > ++optind)
+ if (nargc > optind + 1 && nargv[optind + 1][0] != '-')
+ optarg = nargv[++optind];
+ else
+ optarg = NULL;
+ } else if (nargc > ++optind)
optarg = nargv[optind];
else {
/* option-argument absent */Do you see any issues with it? |
Yes, in it's current state it would segfault on the |
That is strange, I don't see any segmentation faults: |
|
L
I did a clean build. Yes, that seems to work. I will update the PR. |
454445f to
16a4ff8
Compare
|
Please commit the patch attached in: And we'll start from there. |
jlduran
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
The correct trailer should be:
PR:<tab><tab>291374
getopt had an issue when parsing optional arguments if they had a space between the opion and its value. Signed-off-by: Simon Wollwage <[email protected]> PR: 291374
Updated the commit message. Should hopefully be good to go now. |
getopt had an issue when parsing optional arguments if they had a space between the opion and its value.
Request: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=291374
Tested with
bricoler run freebsd-src-regression-suite